from flask_restful import Resource
from comment.models.user import User
from flask import current_app,request,g
from comment.utils.aliyun_sms_send import send_sms
import random
import json
from comment.utils.limiter import limiter
from Shopping.resources.user import constans
from flask_limiter.util import get_remote_address
from comment.utils.shopping_redis import redis_client
from flask_restful.reqparse import RequestParser #专门做参数验证的工具
from comment.utils import parser
from comment.models import db
from comment.utils.token_byPYJWT import generate_tokens
from comment.utils.decorators import login_required
class Shopping_User(Resource):
    '''
    在get函数上加上登录得拦截
    '''
    method_decorators = {
        'get':[login_required]
    }
    def get(self):
        current_app.logger.info('我的测试日志')
        #可能会用到User模型类
        return { 'hello','测试'}
class User_Sms(Resource):
    '''
    发送验证码的函数
    decorators是固定的，不能乱写
    可以传三个参数，限流速率，key_func,超出限制后的提示信息
    '''
    error_mesage='Too many messages'
    decorators = [
        limiter.limit(constans.LIMIT_SMS_CODE_BY_MOBILE,key_func=lambda :request.args['phone'],error_message=error_mesage),
        limiter.limit(constans.LIMIT_SMS_CODE_BY_IP, key_func=get_remote_address,
                      error_message=error_mesage)
    ]
    def get(self):
        phone=request.args['phone'].strip()
        result=send_sms(phone,random.randint(1000,9999))
        #dump(result) #返回的是json格式字符串形式
        result=json.loads(result)#使用json.load的方法将其转化为字典的形式
        result['phone'] = phone
        #短信验证码发送成功后，还需要把验证码存放到redis中，以便于下次验证,
        redis_client.setex("shopping:code:{}".format(phone),constans.SMS_CODE_EXPIRES,code)#参数一：key，手机号,参数二：时效，参数三：验证码
        return result
class AuthorizationCodeResource(Resource):#验证手机验证码
    def post(self):#需要提交手机号和验证码来开始验证
        rp=RequestParser()#初始化RequestParser
        rp.add_argument('phone',type=parser.mobile,required=True)
        rp.add_argument('code',type=parser.regex(r'^\d{4}$'),required=True)
        args=rp.parse_args()
        phone=args.phone
        code =args.code

        #丛redis 数据库中得到之前保存的验证码
        key = 'shopping :code : {}'.format(phone)
        try:
            real_code =redis_client.get(key) #丛redis 中返回时字节数据

        except ConnectionError as e:
            current_app.logger.error(e)
            return  {'message':'redis db connect error.'},400
        #校验
        if not real_code or real_code.decode() != code:
            return {'message':"Invalid code."},400
        return {'phone':phone,'message':'code success.'}

class RegisterUserResource(Resource):
    '''
    填写用户信息，完成注册
    '''
    def post(self):
        rp=RequestParser()
        rp.add_argument('phone',required=True)
        rp.add_argument('username',required=True)
        rp.add_argument('password',required=True)
        rp.add_argument('email',type=parser.email ,required=True)
        '''
        以上为验证工作'''
        args=rp.parse_args()
        username=args.username
        password=args.password
        email=args.email
        phone=args.phone
        #验证用户名是否唯一：先从mysql数据库中根据当前用户查询
        u=User.query.filter(User.username ==username).first()
        if u:#表明该用户已经存在
            current_app.logger.info('{}:用户已经存在，请换一个'.format(username))
            return {'message':'the username already exists'},400
        #将用户信息保存到数据库中
        else:
            u = User(username=username,pwd=password,email=email,status=0)
            db.session.add(u)
            db.session.commit()
            return {'message':'ok'}
#登录功能
class UserLoginResource(Resource):
    def post(self):
        username =request.form.get('username')
        password =request.form.get('password')
        if not all ([username,password]):
            return {'message':'数据不完整'},402
        user = User.query.filter(User.username ==username).first()
        if user :
            if user.check_password(password):
                #必须把用户登录成功之后的用户ID得到token，token返回给前端
                token=generate_tokens(user.id)

                return {'message':'Login Success','token':token,'username':username}
            else:
                return {'message':'用户名或密码错误'},400
class IsExistFormResource(Resource):
    '''
    判断手机号是否存在
    '''
    def post(self):
        phone=request.form.get('phone')
        user=User.query.filter(User.phone==phone).first()
        if user:#如果user不为空，表示改手机号存在
            return {'isExist':True,'message':'此手机号码已经注册','code':203}
        return {'message':'手机号可以注册'}
class UserLoginOutResource(Resource):
    '''
    退出登录
    实现原理：删除全局变量g中的用户信息
    '''
    def post(self):
        if g.user_id:
            g.user_id=None
        return {'msg':'退出登录'}
